package com.mmd.manage.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.mmd.bean.CODE;
import com.mmd.common.entity.*;
import com.mmd.exception.GameException;
import com.mmd.intercepter.AdminInterceptor;
import com.mmd.manage.dao.*;
import com.mmd.manage.service.RouteService;
import com.mmd.manage.vo.*;
import com.mmd.utils.UniqueNoUtils;
import com.mmd.utils.UniqueNoUtils.UniqueNoType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class RouteServiceImpl implements RouteService {
    private Logger log = LoggerFactory.getLogger(RouteServiceImpl.class);

    @Autowired
    private ModeDao modeDao;
    @Autowired
    private AreaDao areaDao;
    @Autowired
    private HscodeDao hscodeDao;
    @Autowired
    private RouteDao routeDao;
    @Autowired
    private MmdSupplierDao mmdSupplierDao;
    @Autowired
    private RouteDetailDao routeDetailDao;
    @Autowired
    private RouteHscodeDao routeHscodeDao;
    @Autowired
    private LogDao logDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private MmdFbaDao mmdFbaDao;
    @Autowired
    private MmdQuotationDao mmdQuotationDao;

    @Override
    public List<MmdFba> getFbaByAreaId(Long areaId) {
        List<MmdArea> areaListByParent = areaDao.getAreaListByParent(areaId);
        List<Long> areaIds = areaListByParent.stream().map(area -> area.getAreaId()).collect(Collectors.toList());
        List<MmdFba> fbaList = mmdFbaDao.selectFbaList(areaIds);
        return fbaList;
    }

    @Override
    public List<MmdMode> getModeList() {
        return modeDao.getModeList();
    }

    @Override
    public List<MmdArea> getAreaList(long parentAreaId) {
        return areaDao.getAreaListByParent(parentAreaId);
    }

    @Override
    public List<MmdRouteDetail> getSonAreaList(long parentAreaId) {
        List<MmdArea> list = areaDao.getAreaListByParent(parentAreaId);
        List<MmdRouteDetail> resultList = new ArrayList<>();
        for (MmdArea area : list) {
            MmdRouteDetail detail = new MmdRouteDetail();
            detail.setSonAreaId(area.getAreaId());
            detail.setSonAreaName(area.getAreaName());
            detail.setAreaRemark(area.getRemark());
            resultList.add(detail);
        }
        return resultList;
    }

    @Override
    public List<RouteHscodeVo> getHscodeList(String keyWord, String quotationNo) {
        List<RouteHscodeVo> hscodeList = hscodeDao.getHscodeList(keyWord);
        if (!StringUtils.isEmpty(quotationNo)) {
            List<RouteHscodeVo> routeHscodeVos = mmdQuotationDao.selectAllHsCode(quotationNo);

            for (RouteHscodeVo mmdHscode : hscodeList) {
                if (!CollectionUtils.isEmpty(routeHscodeVos)) {
                    for (RouteHscodeVo routeHscodeVo : routeHscodeVos) {
                        if (mmdHscode.getHscode().equals(routeHscodeVo.getHscode())) {
                            mmdHscode.setAttachFee(routeHscodeVo.getAttachFee());
                        }
                    }

                }

            }
        }

        return hscodeList;
    }

    @Override
    @Transactional
    public void addRoute(String supplierCode, String routeName, Long modeId, Long areaId, String isem, String detailJson,
                         String hscodeJson, String validStartTimeStr, String validEndTimeStr) {
        MmdRoute route = new MmdRoute();
        route.setRouteNo(UniqueNoUtils.next(UniqueNoType.R));
        route.setRouteName(routeName);
        route.setModeId(modeId);
        route.setIsem(isem);
        MmdMode mode = modeDao.getModeById(modeId);
        if (mode == null) {
            throw new GameException(new CODE(9999, "模式不存在"));
        }
        route.setModeName(mode.getModeName());
        route.setAreaId(areaId);
        MmdArea area = areaDao.getAreaById(areaId);
        if (area == null) {
            throw new GameException(new CODE(9999, "区域不存在"));
        }

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            route.setValidStartTime(format.parse(validStartTimeStr));
            route.setValidEndTime(format.parse(validEndTimeStr));
        }catch (Exception e){
            throw new GameException(new CODE(9999, "有效开始时间或有效结束时间格式错误"));
        }

        if (routeDao.getRouteNumberByTimeBetween(null, routeName,route.getValidStartTime(),route.getValidEndTime()) > 0) {
            throw new GameException(new CODE(9999, "该有效时间内已存在此路线"));
        }

        route.setAreaName(area.getAreaName());
        route.setSupplierCode(supplierCode);
        route.setCreateTime(new Date());
        routeDao.insertRoute(route);

        JSONArray detailJsonArray = JSONObject.parseArray(detailJson);
        for (Object detailObject : detailJsonArray) {
            Map<String, Object> detailMap = (Map<String, Object>) JSONObject.parse(detailObject.toString());
            long sonAreaId = Long.parseLong(detailMap.get("sonAreaId").toString());
            MmdArea sonArea = areaDao.getAreaById(sonAreaId);
            if (sonArea == null) {
                throw new GameException(new CODE(9999, "区域不存在"));
            }
            MmdRouteDetail routeDetail = new MmdRouteDetail();
            if (modeId != 9) {
                BigDecimal kg21 = detailMap.get("kg21") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("kg21").toString());
                BigDecimal kg23 = detailMap.get("kg23") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("kg23").toString());
                BigDecimal kg46 = detailMap.get("kg46") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("kg46").toString());
                BigDecimal kg71 = detailMap.get("kg71") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("kg71").toString());
                BigDecimal kg100 = detailMap.get("kg100") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("kg100").toString());
                BigDecimal kg101 = detailMap.get("kg101") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("kg101").toString());
                BigDecimal kg301 = detailMap.get("kg301") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("kg301").toString());
                BigDecimal kg501 = detailMap.get("kg501") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("kg501").toString());
                BigDecimal kg1001 = detailMap.get("kg1001") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("kg1001").toString());

                routeDetail.setKg21(kg21);
                routeDetail.setKg23(kg23);
                routeDetail.setKg46(kg46);
                routeDetail.setKg71(kg71);
                routeDetail.setKg100(kg100);
                routeDetail.setKg101(kg101);
                routeDetail.setKg301(kg301);
                routeDetail.setKg501(kg501);
                routeDetail.setKg1001(kg1001);
            }else{
                BigDecimal cbm1 = detailMap.get("cbm1") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("cbm1").toString());
                BigDecimal cbm2 = detailMap.get("cbm2") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("cbm2").toString());
                BigDecimal cbm5 = detailMap.get("cbm5") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("cbm5").toString());
                BigDecimal cbm10 = detailMap.get("cbm10") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("cbm10").toString());

                routeDetail.setCbm1(cbm1);
                routeDetail.setCbm2(cbm2);
                routeDetail.setCbm5(cbm5);
                routeDetail.setCbm10(cbm10);
            }

            String drawTime = detailMap.get("drawTime") == null ? null : detailMap.get("drawTime").toString();
            BigDecimal singleOperatFee = detailMap.get("singleOperatFee") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("singleOperatFee").toString());
            BigDecimal singleDeclareFee = detailMap.get("singleDeclareFee") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("singleDeclareFee").toString());
            BigDecimal zgFee = detailMap.get("zgFee") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("zgFee").toString());


            routeDetail.setRouteNo(route.getRouteNo());
            routeDetail.setSonAreaId(sonAreaId);
            routeDetail.setSonAreaName(sonArea.getAreaName());
            routeDetail.setAreaRemark(sonArea.getRemark());
            routeDetail.setDrawTime(drawTime);
            routeDetail.setSingleOperatFee(singleOperatFee);
            routeDetail.setSingleDeclareFee(singleDeclareFee);
            routeDetail.setZgFee(zgFee);
            routeDetailDao.insertRouteDetail(routeDetail);
        }

        if (!StringUtils.isEmpty(hscodeJson)) {
            log.info("hscodeJson===>{}", hscodeJson);
            JSONArray hscodeJsonArray = JSONObject.parseArray(hscodeJson);
            for (Object hscodeObject : hscodeJsonArray) {
                Map<String, Object> hscodeMap = (Map<String, Object>) JSONObject.parse(hscodeObject.toString());
                String hscode = hscodeMap.get("hscode").toString();
                if (hscodeMap.get("attachFee") != null) {
                    BigDecimal attachFee = new BigDecimal(hscodeMap.get("attachFee").toString());
                    MmdRouteHscode routeHscode = new MmdRouteHscode();
                    routeHscode.setRouteNo(route.getRouteNo());
                    routeHscode.setHscode(hscode);
                    routeHscode.setSupplierCode(route.getSupplierCode());
                    routeHscode.setAttachFee(attachFee);
                    routeHscodeDao.insertRouteHscode(routeHscode);
                }
            }
        }

        //添加日志
        MmdLog log = new MmdLog();
        log.setOperatorUid(AdminInterceptor.getUserLoginContext().getUid());
        log.setOperatorKey(route.getRouteNo());
        log.setContent("新增路线");
        log.setCreateTime(new Date());
        logDao.insertLog(log);
    }

    @Override
    @Transactional
    public void modifyRoute(String routeNo, String routeName, Long modeId, Long areaId, String isem, String detailJson,
                            String hscodeJson, String validStartTimeStr, String validEndTimeStr) {
        MmdRoute r = routeDao.getRouteInfo(routeNo);
        if (r == null) {
            throw new GameException(new CODE(9999, "路线不存在"));
        }
        MmdRoute route = new MmdRoute();
        route.setRouteNo(routeNo);
        route.setRouteName(routeName);
        route.setModeId(modeId);
        route.setIsem(isem);
        MmdMode mode = modeDao.getModeById(modeId);
        if (mode == null) {
            throw new GameException(new CODE(9999, "模式不存在"));
        }
        route.setModeName(mode.getModeName());
        route.setAreaId(areaId);
        MmdArea area = areaDao.getAreaById(areaId);
        if (area == null) {
            throw new GameException(new CODE(9999, "区域不存在"));
        }

        long uid = AdminInterceptor.getUserLoginContext().getUid();
        SupplierVo supplier = mmdSupplierDao.getSupplierDetailByUid(uid);
        if (supplier == null) {
            throw new GameException(new CODE(9999, "账号异常"));
        }
        if (!r.getSupplierCode().equals(supplier.getSupplierCode())) {
            throw new GameException(new CODE(9999, "非法操作"));
        }

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            route.setValidStartTime(format.parse(validStartTimeStr));
            route.setValidEndTime(format.parse(validEndTimeStr));
        }catch (Exception e){
            throw new GameException(new CODE(9999, "有效开始时间或有效结束时间格式错误"));
        }

        if (routeDao.getRouteNumberByTimeBetween(routeNo,routeName,route.getValidStartTime(),route.getValidEndTime()) > 0) {
            throw new GameException(new CODE(9999, "该有效时间内已存在此路线"));
        }

        route.setAreaName(area.getAreaName());
        route.setSupplierCode(supplier.getSupplierCode());
        route.setUpdateTime(new Date());
        log.info("updateRoute validStartTime:{}",route.getValidStartTime());
        routeDao.updateRoute(route);

        routeDetailDao.deleteRouteDetail(routeNo);
        JSONArray detailJsonArray = JSONObject.parseArray(detailJson);
        for (Object detailObject : detailJsonArray) {
            Map<String, Object> detailMap = (Map<String, Object>) JSONObject.parse(detailObject.toString());
            long sonAreaId = Long.parseLong(detailMap.get("sonAreaId").toString());
            MmdArea sonArea = areaDao.getAreaById(sonAreaId);
            if (sonArea == null) {
                throw new GameException(new CODE(9999, "区域不存在"));
            }

            MmdRouteDetail routeDetail = new MmdRouteDetail();
            if (modeId != 9) {
                BigDecimal kg21 = detailMap.get("kg21") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("kg21").toString());
                BigDecimal kg23 = detailMap.get("kg23") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("kg23").toString());
                BigDecimal kg46 = detailMap.get("kg46") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("kg46").toString());
                BigDecimal kg71 = detailMap.get("kg71") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("kg71").toString());
                BigDecimal kg100 = detailMap.get("kg100") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("kg100").toString());
                BigDecimal kg101 = detailMap.get("kg101") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("kg101").toString());
                BigDecimal kg301 = detailMap.get("kg301") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("kg301").toString());
                BigDecimal kg501 = detailMap.get("kg501") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("kg501").toString());
                BigDecimal kg1001 = detailMap.get("kg1001") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("kg1001").toString());

                routeDetail.setKg21(kg21);
                routeDetail.setKg23(kg23);
                routeDetail.setKg46(kg46);
                routeDetail.setKg71(kg71);
                routeDetail.setKg100(kg100);
                routeDetail.setKg101(kg101);
                routeDetail.setKg301(kg301);
                routeDetail.setKg501(kg501);
                routeDetail.setKg1001(kg1001);
            }else{
                BigDecimal cbm1 = detailMap.get("cbm1") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("cbm1").toString());
                BigDecimal cbm2 = detailMap.get("cbm2") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("cbm2").toString());
                BigDecimal cbm5 = detailMap.get("cbm5") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("cbm5").toString());
                BigDecimal cbm10 = detailMap.get("cbm10") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("cbm10").toString());

                routeDetail.setCbm1(cbm1);
                routeDetail.setCbm2(cbm2);
                routeDetail.setCbm5(cbm5);
                routeDetail.setCbm10(cbm10);
            }

            BigDecimal singleOperatFee = detailMap.get("singleOperatFee") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("singleOperatFee").toString());
            BigDecimal singleDeclareFee = detailMap.get("singleDeclareFee") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("singleDeclareFee").toString());
            BigDecimal zgFee = detailMap.get("zgFee") == null ? BigDecimal.ZERO : new BigDecimal(detailMap.get("zgFee").toString());


            routeDetail.setRouteNo(route.getRouteNo());
            routeDetail.setSonAreaId(sonAreaId);
            routeDetail.setSonAreaName(sonArea.getAreaName());
            routeDetail.setAreaRemark(sonArea.getRemark());
            if (detailMap.get("drawTime") != null) {
                routeDetail.setDrawTime(detailMap.get("drawTime").toString());
            }
            routeDetail.setSingleOperatFee(singleOperatFee);
            routeDetail.setSingleDeclareFee(singleDeclareFee);
            routeDetail.setZgFee(zgFee);
            routeDetailDao.insertRouteDetail(routeDetail);
        }

        routeHscodeDao.deleteRouteHscode(routeNo);
        if (!StringUtils.isEmpty(hscodeJson)) {
            JSONArray hscodeJsonArray = JSONObject.parseArray(hscodeJson);
            for (Object hscodeObject : hscodeJsonArray) {
                Map<String, Object> hscodeMap = (Map<String, Object>) JSONObject.parse(hscodeObject.toString());

                String hscode = hscodeMap.get("hscode").toString();
                if (hscodeMap.get("attachFee") != null) {
                    BigDecimal attachFee = new BigDecimal(hscodeMap.get("attachFee").toString());
                    MmdRouteHscode routeHscode = new MmdRouteHscode();
                    routeHscode.setRouteNo(route.getRouteNo());
                    routeHscode.setHscode(hscode);
                    routeHscode.setSupplierCode(route.getSupplierCode());
                    routeHscode.setAttachFee(attachFee);
                    routeHscodeDao.insertRouteHscode(routeHscode);
                }
            }
        }

        //添加日志
        MmdLog log = new MmdLog();
        log.setOperatorUid(uid);
        log.setOperatorKey(route.getRouteNo());
        log.setContent("修改路线");
        log.setCreateTime(new Date());
        logDao.insertLog(log);
    }

    @Override
    public RouteVo getRouteInfo(String routeNo) {
        MmdRoute route = routeDao.getRouteInfo(routeNo);
        if (route == null) {
            throw new GameException(new CODE(9999, "路线不存在"));
        }

        RouteVo routeVo = new RouteVo();
        BeanUtils.copyProperties(route, routeVo);
        routeVo.setRouteDetailList(routeDetailDao.getRouteDetail(routeNo));
        List<RouteHscodeVo> routeHscodeVoList = hscodeDao.getHscodeListByRoute(null, routeNo);

        routeVo.setRouteHscodeList(routeHscodeVoList);
        return routeVo;
    }

    @Override
    public List<MmdRoute> getRouteNameList(long uid) {
        MmdUser mmdUser = userDao.selectByPrimaryKey(uid);
        log.info("查询用户信息：{}", JSON.toJSONString(mmdUser));
        if (mmdUser == null) {
            throw new GameException(new CODE(9999, "账号异常"));
        }
        MmdSupplier mmdSupplier = new MmdSupplier();
        List<MmdSupplier> supplier = null;
        if ("admin".equals(mmdUser.getLevel())) {
            supplier = mmdSupplierDao.selectByKeySelective(mmdSupplier);
        } else {
            mmdSupplier.setAccountUid(uid);
            supplier = mmdSupplierDao.selectByKeySelective(mmdSupplier);
        }

        if (CollectionUtils.isEmpty(supplier)) {
            throw new GameException(new CODE(9999, "账号异常"));
        }
        return routeDao.getRouteListBySupplierCodeList(supplier);
    }

    @Override
    public List<RouteValidTimeVo> getValidTimeByRouteName(String routeName) {
        if (StringUtils.isEmpty(routeName)) {
            throw new GameException(new CODE(9999, "请选择路线"));
        }
//        if (StringUtils.isEmpty(modeId)) {
//            throw new GameException(new CODE(9999, "请选择渠道"));
//        }
//        if (areaId == null) {
//            throw new GameException(new CODE(9999, "请选择区域"));
//        }

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        List<MmdRoute> quotationList = routeDao.getRouteByRouteName(routeName);
        List<RouteValidTimeVo> resultList = quotationList.stream().map(mmdRoute -> {
            RouteValidTimeVo routeValidTimeVo = new RouteValidTimeVo();
            routeValidTimeVo.setRouteNo(mmdRoute.getRouteNo());

            if (mmdRoute.getValidStartTime() != null && mmdRoute.getValidEndTime() != null){
                String validStartTimeStr = format.format(mmdRoute.getValidStartTime());
                String validEndTimeStr = format.format(mmdRoute.getValidEndTime());
                routeValidTimeVo.setValidTimeArea(validStartTimeStr + "~" + validEndTimeStr);
            }

            return routeValidTimeVo;
        }).collect(Collectors.toList());
        return resultList;
    }

    @Override
    public List<RouteVo> getRouteListBySupplier(long uid) {
        MmdUser mmdUser = userDao.getUserByUid(uid);

        MmdSupplier mmdSupplier = new MmdSupplier();
        List<MmdSupplier> suppliers = null;
        if ("admin".equals(mmdUser.getLevel())) {
            suppliers = mmdSupplierDao.selectByKeySelective(mmdSupplier);
        } else {
            mmdSupplier.setAccountUid(uid);
            suppliers = mmdSupplierDao.selectByKeySelective(mmdSupplier);
        }
        if (suppliers == null) {
            throw new GameException(new CODE(9999, "账号异常"));
        }
        List<MmdRoute> routeList = routeDao.getRouteListBySupplierCodeList(suppliers);
        List<RouteVo> resultList = new ArrayList<>();
        for (MmdRoute route : routeList) {
            RouteVo routeVo = new RouteVo();
            BeanUtils.copyProperties(route, routeVo);
            routeVo.setRouteDetailList(routeDetailDao.getRouteDetail(route.getRouteNo()));

            List<RouteHscodeVo> routeHscodeVoList = routeHscodeDao.getRouteHscodeVo(route.getRouteNo());
            MmdSupplier mmdSupplier1 = mmdSupplierDao.selectByPrimaryKey(route.getSupplierCode());

            routeVo.setSupplierName(mmdSupplier1.getSupplierName());
            routeVo.setRouteHscodeList(routeHscodeVoList);
            resultList.add(routeVo);
        }
        return resultList;
    }

    @Override
    public List<MmdRoute> getRouteList(String supplierCode) {
//        List<MmdRoute> routeListBySupplier = routeDao.getRouteListBySupplier(supplierCode);
        List<MmdRoute> routeListBySupplier = routeDao.getValidRouteListBySupplier(supplierCode);
        for (MmdRoute mmdRoute : routeListBySupplier) {
            String sb = mmdRoute.getAreaName() +
                    " > " + mmdRoute.getModeName() +
                    " > " + mmdRoute.getRouteName();
            mmdRoute.setRouteName(sb);
        }
        return routeListBySupplier;
    }
}
